home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / New System Software Extensions / PlainTalk™ Speech Technologies / Text to Speech / Programming Stuff / Examples / SpeakFile / Simple App.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-15  |  19.3 KB  |  848 lines  |  [TEXT/KAHL]

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <Speech.h>
  4. #include <GestaltEqu.h>
  5.  
  6. #include "BigEasy.h"
  7. #include "Globals.h"
  8.  
  9. #define    LoMemROM85            (* (unsigned short*) ROM85)    /* ROM version */
  10. #define    HaveCQD()            (LoMemROM85 <= 0x3FFF)        /* true if color quickdraw is present */
  11.  
  12. #define kMaxLines            20000
  13. #define kTextBufLen            100000
  14.  
  15. #define kDisplayFont        (monaco)                    /* Font characteristics for window displays */
  16. #define kDisplaySize        9
  17. #define kDisplayFace        0
  18. #define kScrollBarPixels    16
  19.  
  20. #define kAboutID            128                            /* About box dialog ID */
  21.  
  22. #define kWindowTop            40
  23. #define kWindowLeft            3
  24. #define kWindowBottom        340
  25. #define kWindowRight        510
  26. #define kDefaultNewWindowRect     {kWindowTop, kWindowLeft, kWindowBottom, kWindowRight}     /* Top, Left, Bottom, Right */
  27. #define kWindowBaseX            5
  28. #define kWindowBaseY            15
  29.  
  30. GlobalsPtr        globals = nil;
  31. char            gStr[512];
  32. ushort            gStrLen = 0;
  33. Boolean            gPrintFlag = true;
  34. Handle            gText = nil;        // Handle to the text we want to speak
  35. VoiceSpec        gVoiceSpec[32];
  36. short            gCurrentVoice;        // index of current voice spec
  37. SpeechChannel    gSpeechChannel = nil;
  38. Fixed            gSpeechRate = 0;
  39.  
  40. /*    =============================
  41.         External Routines
  42.     ============================= */
  43.  
  44. // PRIVATE TRAP DEFINES TO DO TIMING MEASUREMENTS
  45.  
  46. //struct Int64Bit {
  47. // long hiLong;
  48. // long loLong;
  49. //};
  50.  
  51. //typedef struct Int64Bit Int64Bit;
  52.  
  53. // this returns the number of microseconds but isn't yet defined for the public
  54. #pragma parameter Microseconds(__A1)
  55. pascal void Microseconds(Int64Bit *microsecondCount) =
  56.   {0xA193,0x22C8,0x2280};
  57.  
  58. /*    =============================
  59.         Function Prototypes
  60.     ============================= */
  61.  
  62. void            AddLineToTextDisplay(GlobalsPtr g, char *formatStr, ulong value);
  63. void            AddStringToTextDisplay(GlobalsPtr g, char *str);
  64. void            InitTextDisplay(GlobalsPtr g);
  65. void            ComputeWindowLines(GlobalsPtr g);
  66. void            RefreshWindow(GlobalsPtr g);
  67. void            PageDown(GlobalsPtr g);
  68. void            PageUp(GlobalsPtr g);
  69. void            GoToLine(GlobalsPtr g, ulong line);
  70. void            UpdateDisplay(GlobalsPtr g);
  71. void            DoClick(Ptr storage, Point p, short mods, long when);
  72. void            DoUpdate(Ptr storage);
  73. void            DoIdle(Ptr storage);
  74. void            DoMyClose(Ptr storage);
  75. void            OpenNewWindow(void);
  76. void            DoAbout(void);
  77. void            MenuPageUp(void);
  78. void            MenuPageDown(void);
  79. void            MenuLineUp(void);
  80. void            MenuLineDown(void);
  81. void            MenuGoToTop(void);
  82. void            MenuGoToBottom(void);
  83. void            MenuTimeTest(void);
  84. void            Wait(unsigned long ticks);
  85. void            DoOpen(void);
  86. void            BuildVoiceMenu(void);
  87. void            MenuVoiceSelect(void);
  88. void            MenuTalk(void);
  89. void            MenuShutUp(void);
  90. void            Bootstrap(void);
  91.  
  92. /*    =============================
  93.             Window Methods
  94.     ============================= */
  95.  
  96. void AddLineToTextDisplay(GlobalsPtr g, char * formatStr, ulong value)
  97. {
  98.     char    s[256];
  99.     short    len;
  100.  
  101.     len = sprintf(s, formatStr, value);
  102.  
  103.     if (((g->textLen + len) >= kTextBufLen)
  104.     ||  (g->numLines >= kMaxLines)
  105.     ||  (!g->lineStarts)
  106.     ||  (!g->lines))
  107.         return;
  108.     
  109.     g->lineStarts[g->numLines] = g->textLen;            // save ptr to this line
  110.  
  111.     BlockMove(s, &g->lines[g->textLen], len);            // copy text into line text buffer
  112.  
  113.     g->textLen += len;                                    // increment our write ptr
  114.     g->numLines++;                                        // and increment our line count
  115.  
  116.     g->lineStarts[g->numLines] = g->textLen;            // save ptr to end of text
  117. }
  118.  
  119. void AddStringToTextDisplay(GlobalsPtr g, char * str)
  120. {
  121.     char    s[256];
  122.     short    len;
  123.  
  124.     len = sprintf(s, str);
  125.  
  126.     if (((g->textLen + len) >= kTextBufLen)
  127.     ||  (g->numLines >= kMaxLines)
  128.     ||  (!g->lineStarts)
  129.     ||  (!g->lines))
  130.         return;
  131.     
  132.     g->lineStarts[g->numLines] = g->textLen;            // save ptr to this line
  133.  
  134.     BlockMove(s, &g->lines[g->textLen], len);            // copy text into line text buffer
  135.  
  136.     g->textLen += len;                                    // increment our write ptr
  137.     g->numLines++;                                        // and increment our line count
  138.  
  139.     g->lineStarts[g->numLines] = g->textLen;            // save ptr to end of text
  140. }
  141.  
  142. void InitTextDisplay(GlobalsPtr g)
  143. {
  144.     g->curLine  = 0;
  145.     g->numLines = 0;
  146.     g->textLen  = 0;
  147.     g->lines     = nil;
  148.     g->lineStarts = nil;
  149.     
  150.     // allocate space to hold the text and line start info and then 
  151.     // compute the display lines for real this time
  152.     
  153.     g->lineStarts = (ulong *) NewPtrClear(sizeof(ulong) * kMaxLines);      // allocate space for line starts array
  154.     if (!g->lineStarts)                                        // could not allocate line start buffer
  155.         TrapError("\p InitTextDisplay:  Could not allocate lineStarts buffer", MemError(), true, true);  // FATAL ERROR
  156.  
  157.     g->lines = NewPtrClear(kTextBufLen);                    // allocate space for display text
  158.     if (!g->lines)                                            // could not allocate display text buffer
  159.         TrapError("\p InitTextDisplay:  Could not allocate lines buffer", MemError(), true, true);  // FATAL ERROR
  160.  
  161.     g->lineStarts[g->numLines] = g->textLen;                    // save ptr to end of text
  162. }
  163.  
  164. void ComputeWindowLines(GlobalsPtr g)
  165. {
  166.     Rect        clip;
  167.     FontInfo    f;
  168.     
  169.     clip = g->theWindow->portRect;
  170.     clip.right  -= kScrollBarPixels;    // stop drawing at scroll bar and grow icon boundaries
  171.     clip.bottom -= kScrollBarPixels;
  172.     
  173.     GetFontInfo(&f);
  174.     g->lineHeight = f.ascent + f.descent + f.leading;
  175.     g->displayLines = (clip.bottom - clip.top)/g->lineHeight;    // number of lines we can display
  176. }
  177.  
  178. void RefreshWindow(GlobalsPtr g)            // repaint window info
  179. {
  180.     PenState    savePen;
  181.     RgnHandle    saveClip;
  182.     Rect        clip;
  183.     ulong        linePtr;
  184.     short         lineLen;
  185.     short        i;
  186.     Point        pen;
  187.     FontInfo    f;
  188.     
  189.  
  190.     if (!g)                return;
  191.     if (!g->theWindow)    return;
  192.     if (!g->numLines)    return;    // no lines to display
  193.     if (!g->lines)         return;
  194.         
  195.     saveClip = NewRgn();
  196.     if (!saveClip)    return;
  197.     
  198.     GetClip(saveClip);
  199.     clip = g->theWindow->portRect;
  200.     clip.right  -= kScrollBarPixels;    // stop drawing at scroll bar and grow icon boundaries
  201.     clip.bottom -= kScrollBarPixels;
  202.     ClipRect(&clip);
  203.     
  204.     ComputeWindowLines(g);                // make sure our globals are set correctly
  205.         
  206.     for (i = 0; i < g->displayLines; i++)
  207.     {
  208.         if ((g->curLine + i) >= g->numLines) break;
  209.         
  210.         linePtr = g->lineStarts[g->curLine + i];        // get ptr to the text for this line
  211.         lineLen = g->lineStarts[g->curLine + i + 1] - linePtr;
  212.         
  213.         MoveTo(kWindowBaseX,kWindowBaseY + (i * g->lineHeight));
  214.         DrawText(&g->lines[linePtr], 0, lineLen);
  215.     }
  216.     
  217.     SetClip(saveClip);
  218.     DisposeRgn(saveClip);
  219. }
  220.  
  221. void PageDown(GlobalsPtr g)
  222. {
  223.     ulong    oldLine = g->curLine;
  224.         
  225.     g->curLine += g->displayLines;
  226.     
  227.     if (g->curLine > (g->numLines -1))
  228.         g->curLine = g->numLines - 1;
  229.         
  230.     if (g->curLine != oldLine)
  231.         InvalRect(&g->theWindow->portRect);
  232. }
  233.  
  234. void PageUp(GlobalsPtr g)
  235. {
  236.     ulong    oldLine = g->curLine;
  237.     
  238.     if (g->curLine > g->displayLines)
  239.         g->curLine -= g->displayLines;
  240.     else
  241.         g->curLine = 0;
  242.         
  243.     if (g->curLine != oldLine)
  244.         InvalRect(&g->theWindow->portRect);
  245. }
  246.  
  247. void GoToLine(GlobalsPtr g, ulong line)
  248. {
  249.     if (line > (g->numLines - 1))
  250.         line = g->numLines - 1;
  251.     
  252.     if (g->curLine != line)
  253.     {
  254.         g->curLine = line;
  255.         InvalRect(&g->theWindow->portRect);
  256.     }
  257. }
  258.  
  259. void UpdateDisplay(GlobalsPtr g)
  260. {
  261.      ComputeWindowLines(g);
  262.     GoToLine(g, (g->numLines > g->displayLines) ? g->numLines - g->displayLines : 0);
  263.     RefreshWindow(g);
  264. }
  265.  
  266. void DoClick(Ptr storage, Point p, short mods, long when)
  267. {
  268.     GlobalsPtr    g = (GlobalsPtr) storage;
  269.     Point        mousePt;
  270.     short         middle;
  271.     short         windowHeight = g->theWindow->portRect.bottom - g->theWindow->portRect.top - kScrollBarPixels;
  272.     short        clickHeight;
  273.     ulong        line;
  274.         
  275.     mousePt = p;
  276.     GlobalToLocal(&mousePt);
  277.  
  278.     if ((mods & cmdKey)                                    /* cmd key held down means simulate scroll bar */
  279.     ||    (mousePt.h > (g->theWindow->portRect.right - kScrollBarPixels)))
  280.     {
  281.         clickHeight = mousePt.v - g->theWindow->portRect.top;
  282.         
  283.         line = g->numLines * clickHeight / windowHeight;
  284.         
  285.         GoToLine(g, line);
  286.     }
  287.     else
  288.     {
  289.         middle = g->theWindow->portRect.top + ((g->theWindow->portRect.bottom - g->theWindow->portRect.top)/2);
  290.         
  291.         if (mousePt.v > middle)                // clicked in lower half of window
  292.             PageDown(g);
  293.         else                                // clicked in upper half of window
  294.             PageUp(g);
  295.     }
  296. }
  297.  
  298. void DoUpdate(Ptr storage)
  299. {
  300.     GlobalsPtr    g = (GlobalsPtr) storage;
  301.  
  302.     EraseRect(&g->theWindow->portRect);        // Erase the whole window    
  303.     DrawGrowIcon(g->theWindow);
  304.      
  305.     RefreshWindow(g);                        // repaint window info
  306. }
  307.  
  308. void DoIdle(Ptr storage)
  309. {
  310.     GlobalsPtr    g = (GlobalsPtr) storage;
  311.     double        a,w;
  312.     long        mem, x;
  313.     THz            zone;
  314.     #define     kTwoPi (3.14159265 * 2)
  315.     
  316.     if (g->idlePurgeCompact) {
  317.         zone = GetZone();
  318.         
  319.         x = 0xFFFFFFFF;
  320.         SetZone(ApplicZone());
  321.         PurgeMem(x);
  322.         mem = CompactMem(x);
  323.         SetZone(SystemZone());
  324.         PurgeMem(x);
  325.         mem = CompactMem(x);
  326.  
  327.         SetZone(zone);
  328.     }
  329.     
  330.     if (g->idleTrigCalcs) {
  331.         for (a = 0; a < kTwoPi; ) {
  332.             w += log(abs(atan(cos(a) * sin(a))));
  333.             a += kTwoPi/256;
  334.         }
  335.     }
  336. }
  337.  
  338. void DoMyClose(Ptr storage)
  339. {
  340.     GlobalsPtr    g = (GlobalsPtr) storage;
  341.     OSErr err;
  342.  
  343.     /*    First thing to do is to free up all the RAM we allocated for this window.
  344.         Here's what might be sitting around:
  345.         
  346.             Ptrs
  347.             ----
  348.             g->inBuf
  349.             g->lines
  350.             g->lineStarts
  351.     */
  352.  
  353.     if (g->lines) DisposPtr(g->lines);
  354.     g->lines = nil;
  355.         
  356.     if (g->lineStarts) DisposPtr((Ptr) g->lineStarts);
  357.     g->lineStarts = nil;
  358.     
  359.     UninstallWindow(g->theWindow);
  360.     g->theWindow = nil;
  361. }
  362.  
  363. void OpenNewWindow(void)
  364. {
  365.     GlobalsPtr    g = nil;
  366.     WindowPtr    theWindow = nil;
  367.     Rect        r = kDefaultNewWindowRect;
  368.     OSErr        err;
  369.         
  370.     g = (GlobalsPtr) InstallWindow(&r, documentProc, true, "\pHey, It's Just A Test…",
  371.                     DoUpdate, DoClick, DefaultGrow, DefaultKey, DoMyClose, DefaultDeath,
  372.                     DefaultActivate, DefaultDeactivate, DoIdle, sizeof(GlobalsRecord),
  373.                     &theWindow);
  374.  
  375.     if (g)
  376.     {
  377.         g->theWindow = (WindowPtr) theWindow;
  378.         g->numLines     = 0;            // initialize text display info
  379.         g->textLen         = 0;
  380.         g->lines         = nil;
  381.         g->lineStarts     = nil;
  382.         g->curLine         = 0;
  383.         
  384.         ShowWindow(theWindow);
  385.         
  386.          SetPort(theWindow);
  387.         TextFont(kDisplayFont);            // set the text drawing modes for our window
  388.         TextSize(kDisplaySize);
  389.         TextFace(kDisplayFace);
  390.         TextMode(srcCopy);
  391.  
  392.         InitTextDisplay(g);                // and set up data structures to display the converted file
  393.         
  394.         globals = g;                    // used by VoiceSearch()
  395.         gStrLen = 0;    
  396.             
  397.     }
  398. }
  399.  
  400. /*    =============================
  401.             Menu Methods
  402.     ============================= */
  403.  
  404. void DoAbout(void)
  405. {
  406.     DialogPtr    dialog;
  407.     short        item;
  408.     
  409.     dialog = GetNewDialog(kAboutID, nil, (WindowPtr) -1);
  410.     if (!dialog) return;
  411.     
  412.     ModalDialog(nil, &item);
  413.     
  414.     DisposeDialog(dialog);
  415. }
  416.  
  417. void MenuPageUp(void)
  418. {
  419.     PageUp((GlobalsPtr) GetWindowStorage(FrontWindow()));
  420. }
  421.  
  422. void MenuPageDown(void)
  423. {
  424.     PageDown((GlobalsPtr) GetWindowStorage(FrontWindow()));
  425. }
  426.  
  427. void MenuLineUp(void)
  428. {
  429.     GlobalsPtr    g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  430.     
  431.     if (g->curLine)
  432.         GoToLine(g, g->curLine - 1);
  433. }
  434.  
  435. void MenuLineDown(void)
  436. {
  437.     GlobalsPtr    g;
  438.     
  439.     g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  440.  
  441.     if (g->curLine < (g->numLines - 1))
  442.         GoToLine(g, g->curLine + 1);
  443. }
  444.  
  445.  
  446. void MenuGoToTop(void)
  447. {
  448.     GoToLine((GlobalsPtr) GetWindowStorage(FrontWindow()), 0);
  449. }
  450.  
  451. void MenuGoToBottom(void)
  452. {
  453.     GlobalsPtr    g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  454.     
  455.     GoToLine(g, g->numLines);
  456. }
  457.  
  458.  
  459. #define NOW  (*(unsigned long *)  0x016A)    // Ticks = 0x16A, /*[GLOBAL VAR] Current number of ticks since system startup (long)
  460. #define DBRA (*(unsigned short *) 0x0D00)    // TimeDBRA = 0x0D00, /*[GLOBAL VAR]  (word) number of iterations of DBRA per millisecond*/
  461.  
  462. void MenuTimeTest(void)
  463. {
  464.     GlobalsPtr        g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  465.     Int64Bit        start, end;
  466.     unsigned short    count = DBRA - 1; // pick up TimeDBRA value
  467.     unsigned long     t;
  468.     long            microTrap = NGetTrapAddress(0xA193, OSTrap); // get addr of Microseconds trap routine
  469.     
  470.     t = NOW;
  471.     
  472.     while (t == NOW);
  473.     
  474.     t = NOW;
  475.     
  476.     Microseconds(&start);
  477.     
  478.     while (t == NOW);
  479.  
  480.     Microseconds(&end);
  481.  
  482.     ShowNumCR("Elapsed Microseconds in 1 Tick: %lu", end.loLong-start.loLong);
  483.  
  484.     ShowNumCR("TimeDBRA:   %hu", (unsigned short) (*(unsigned short *) 0x0D00));
  485.     ShowNumCR("DBRA Count: %hu", (unsigned short) count);
  486.     
  487.     asm {
  488.         move    sr,-(sp)            ; save interrupt status
  489.         ori        #0x0700,sr            ; mask off all interrupts
  490.         
  491.         ; inline call to the Microseconds trap
  492.         lea        start,a1
  493.         move.l     microTrap, a0
  494.         jsr     (a0) 
  495.         move.l    d0, start.loLong    ; only take the lower word
  496.     }
  497.     
  498. //    Microseconds(&start);
  499.  
  500.     asm {
  501.                 move.w    count,d0
  502.         @loop:    dbra    d0,@loop
  503.     }
  504.  
  505. //    Microseconds(&end);
  506.  
  507.     asm {
  508.         ; inline call to the Microseconds trap
  509.         lea        end,a1
  510.         move.l     microTrap, a0
  511.         jsr     (a0) 
  512.         move.l    d0, end.loLong        ; only take the lower word
  513.  
  514.         move    (sp)+,sr            ; restore interrupts
  515.     }
  516.  
  517.     ShowNumCR("Elapsed Microseconds: %lu", end.loLong-start.loLong);
  518.  
  519.      ComputeWindowLines(g);
  520.     
  521.     GoToLine(g, (g->numLines > g->displayLines) ? g->numLines - g->displayLines : 0);
  522.     
  523.     RefreshWindow(g);
  524. }
  525.  
  526. void Wait (unsigned long ticks)
  527. {
  528.     unsigned long stopTime = NOW + ticks;
  529.     
  530.     while (NOW < stopTime);
  531. }
  532.  
  533.  
  534. void MenuGetTextFile( void )
  535. {
  536.     SFReply            theReply;
  537.     Point             where = {20, 90};
  538.     SFTypeList        typeList = {'TEXT'};
  539.     OSErr            err;
  540.     short            fRefNum = 0;
  541.     long             fileLen;
  542.     Handle            textHandle = nil;
  543.     
  544.     MenuShutUp();                            // stop any active speech
  545.     
  546.     SFGetFile(where, 0, 0, 1, typeList, 0, &theReply); /* get a text file */
  547.     
  548.     if (theReply.good)
  549.     {
  550.         err = FSOpen(theReply.fName, theReply.vRefNum, &fRefNum); /* Open the file */
  551.         if (err) {                            /* failed on open */
  552.             fRefNum = 0;
  553.             goto BOMB_OUT;
  554.         }
  555.         
  556.         err = GetEOF(fRefNum, &fileLen);    /* find out how long file is */
  557.         if (err) goto BOMB_OUT;
  558.         
  559.         textHandle = NewHandle(fileLen);     /* get some memory to hold text */
  560.         if (!textHandle) {
  561.             err = MemError();
  562.             goto BOMB_OUT;
  563.         }
  564.         
  565.         MoveHHi(textHandle);
  566.         HLock(textHandle);
  567.         
  568.         err = FSRead(fRefNum, &fileLen, *textHandle); /* read in the text */
  569.         if (err) goto BOMB_OUT;
  570.                     
  571.         FSClose(fRefNum);                    /* close the disk file */
  572.     }
  573.         
  574.     if (gText)                                // free up any prior text data handle
  575.         DisposeHandle(gText);
  576.         
  577.     gText = textHandle;                        // save handle to new text data
  578.     
  579.     return;                                    // everything worked
  580.  
  581.     //______________ ERROR HANDLERS ________________________________________
  582.  
  583.     BOMB_OUT:
  584.         SysBeep(10);                        // should put up some alert here!
  585.         
  586.         if (fRefNum != 0)                    // opened a file
  587.             FSClose(fRefNum);                // close it
  588.         
  589.         if (textHandle)                        // allocated some RAM
  590.             DisposeHandle(textHandle);        // free it up
  591. }
  592.  
  593. void BuildVoiceMenu(void)
  594. {
  595.     OSErr                err;
  596.     short                voiceCount;
  597.     short                i;
  598.     VoiceDescription    vd;
  599.                                     
  600.     InstallMenu("\pVoices");
  601.     InstallItem("\pDefault Voice", MenuVoiceSelect);
  602.     
  603.     err = CountVoices(&voiceCount);
  604.     
  605.     for (i = 1; i <= voiceCount; i++) {
  606.         err = GetIndVoice(i, &gVoiceSpec[i]);
  607.         err = GetVoiceDescription(&gVoiceSpec[i], &vd, sizeof(VoiceDescription));
  608.         
  609.         InstallItem(vd.name, MenuVoiceSelect);
  610.     }
  611.     
  612.     gCurrentVoice = 0;                        // use Default voice
  613. }
  614.  
  615. void MenuVoiceSelect (void)
  616. {
  617.     gCurrentVoice = LoWrd(gLastMenuSelect) - 1;
  618. }
  619.  
  620. void MenuTalk (void)
  621. {    
  622.     OSErr    err;
  623.  
  624.     if (gSpeechChannel) {
  625.         err = DisposeSpeechChannel(gSpeechChannel);
  626.         gSpeechChannel = nil;
  627.     }
  628.     
  629.     if (gText) {
  630.         if (gCurrentVoice == 0)
  631.             err = NewSpeechChannel(0, &gSpeechChannel);
  632.         else
  633.             err = NewSpeechChannel(&gVoiceSpec[gCurrentVoice], &gSpeechChannel);
  634.         
  635.         if (err == noErr) {
  636.             if (gSpeechRate)
  637.                 err = SetSpeechInfo(gSpeechChannel, soRate, &gSpeechRate);
  638.             err = SpeakText(gSpeechChannel, *gText, GetHandleSize(gText));
  639.         }
  640.     }
  641.     else
  642.         SysBeep(1);
  643. }
  644.  
  645. void MenuShutUp (void)
  646. {
  647.     OSErr err;
  648.     
  649.     if (gSpeechChannel) {
  650.         err = DisposeSpeechChannel(gSpeechChannel);
  651.         gSpeechChannel = nil;
  652.     }
  653. }
  654.  
  655. void MenuSystemVersionTest (void)
  656. {
  657.     GlobalsPtr        g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  658.     OSErr     err;
  659.     long    systemVersion;
  660.     
  661.     err = Gestalt(gestaltSystemVersion, &systemVersion); // get our system version
  662.     
  663.     ShowNumCR("System Version: %lx", systemVersion);
  664.     UpdateDisplay(g);
  665. }
  666.  
  667. void MenuToggleIdleTrigCalcs (void)
  668. {
  669.     GlobalsPtr        g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  670.     
  671.     g->idleTrigCalcs = !g->idleTrigCalcs;    // toggle idle calcs variable
  672.     
  673.     if (g->idleTrigCalcs) {
  674.         ShowStrCR("Starting idle time trigonometric calculations…");
  675.     }
  676.     else {
  677.         ShowStrCR("Stopping idle time trigonometric calculations…");
  678.     }
  679.     
  680.     UpdateDisplay(g);
  681. }
  682.  
  683. void MenuTogglePurgeCompact (void)
  684. {
  685.     GlobalsPtr        g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  686.     
  687.     g->idlePurgeCompact = !g->idlePurgeCompact;    // toggle idle purge variable
  688.     
  689.     if (g->idlePurgeCompact) {
  690.         ShowStrCR("Starting idle time memory purge & compact…");
  691.     }
  692.     else {
  693.         ShowStrCR("Stopping idle time memory purge & compact…");
  694.     }
  695.     
  696.     UpdateDisplay(g);
  697. }
  698.  
  699. void MenuQuit (void)
  700. {
  701.     MenuShutUp();    // shut down any speech
  702.     DoQuit();        // call normal shut down routine in Big Easy    
  703. }
  704.  
  705. void MenuMeasureRAM (void)
  706. {
  707.     GlobalsPtr    g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  708.     long        mem, x;
  709.     long        appTotal, appContig;
  710.     long        sysTotal, sysContig;
  711.     long        appMem, sysMem;
  712.     THz            zone;
  713.  
  714.     zone = GetZone();
  715.     
  716.     #if 1
  717.         SetZone(ApplicZone());
  718.         PurgeSpace(&appTotal, &appContig);
  719.         SetZone(SystemZone());
  720.         PurgeSpace(&sysTotal, &sysContig);
  721.         appMem = appTotal;
  722.         sysMem = sysTotal;
  723.     #else
  724.         x = 0xFFFFFFFF;
  725.         SetZone(ApplicZone());
  726.         PurgeMem(x);
  727.         mem = CompactMem(x);
  728.         appMem = FreeMem();
  729.         
  730.         SetZone(SystemZone());
  731.         PurgeMem(x);
  732.         mem = CompactMem(x);
  733.         sysMem = FreeMem();
  734.     #endif
  735.     
  736.     SetZone(zone);
  737.     
  738.     ShowNumCR("Application Heap Available: %ld", appMem);
  739.     ShowNumCR("System Heap Available: %ld", sysMem);
  740.  
  741.     UpdateDisplay(g);
  742. }
  743.  
  744.  
  745. void MenuSpeakFaster (void)
  746. {
  747.     GlobalsPtr    g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  748.     Fixed        rate, newRate, oldRate;
  749.     OSErr        err;
  750.     
  751.     if (gSpeechChannel) {
  752.         err = GetSpeechRate(gSpeechChannel, &oldRate);
  753.         rate = newRate = oldRate;
  754.         
  755.         while (rate == oldRate) {
  756.             newRate += (1 << 16);
  757.             
  758.             if (abs(newRate - oldRate) > (150 << 16)) 
  759.                 break;    // bust out if we aren't getting anywhere
  760.             
  761.             err = SetSpeechRate(gSpeechChannel, newRate);
  762.             err = GetSpeechRate(gSpeechChannel, &rate);
  763.         }
  764.         
  765.         gSpeechRate = rate;                // save the new rate
  766.         
  767.         ShowNumCR("New Speaking Rate: %f", rate/65536.0);
  768.         UpdateDisplay(g);
  769.     }
  770. }
  771.  
  772. void MenuSpeakSlower (void)
  773. {
  774.     GlobalsPtr    g = (GlobalsPtr) GetWindowStorage(FrontWindow());
  775.     Fixed        rate, newRate, oldRate;
  776.     OSErr        err;
  777.     
  778.     if (gSpeechChannel) {
  779.         err = GetSpeechRate(gSpeechChannel, &oldRate);
  780.         rate = newRate = oldRate;
  781.         
  782.         while (rate == oldRate) {
  783.             newRate -= (1 << 16);
  784.             
  785.             if ((abs(oldRate - newRate) > (150 << 16)) 
  786.             ||  (newRate < (1 << 16)))
  787.                 break;    // bust out if we aren't getting anywhere
  788.             
  789.             err = SetSpeechRate(gSpeechChannel, newRate);
  790.             err = GetSpeechRate(gSpeechChannel, &rate);
  791.         }
  792.         
  793.         gSpeechRate = rate;                // save the new rate
  794.         
  795.         ShowNumCR("New Speaking Rate: %f", rate/65536.0);
  796.     
  797.         UpdateDisplay(g);
  798.     }
  799. }
  800.  
  801. /*    =============================
  802.          Main Entry Point
  803.     ============================= */
  804.     
  805. void Bootstrap(void)
  806. {    
  807.       InstallMenu("\pFile");
  808. /*    InstallItem("\pNew/N", OpenNewWindow);*/
  809.     InstallItem("\pOpen/O", MenuGetTextFile);
  810. /*    InstallItem("\pClose/W", DoCloseWindow);*/
  811.     InstallItem("\p(-", nil);
  812.     InstallItem("\pQuit/Q", MenuQuit);
  813.     
  814.     InstallEditMenu(nil,nil,nil,nil,nil);
  815.     
  816. /*  InstallMenu("\pPosition");*/
  817. /*    InstallItem("\pTop/T", MenuGoToTop);*/
  818. /*    InstallItem("\pBottom/B", MenuGoToBottom);*/
  819. /*    InstallItem("\pPage Up/U", MenuPageUp);*/
  820. /*    InstallItem("\pPage Down/D", MenuPageDown);*/
  821. /*    InstallItem("\pLine Up/¨", MenuLineUp);*/
  822. /*    InstallItem("\pLine Down/∂", MenuLineDown);*/
  823.     
  824.     InstallMenu("\pSpeech");
  825.     InstallItem("\pTalk/T", MenuTalk);
  826.     InstallItem("\pShutUp/.", MenuShutUp);
  827.     InstallItem("\p(-", nil);
  828.     InstallItem("\pSpeak Faster/=", MenuSpeakFaster);
  829.     InstallItem("\pSpeak Slower/-", MenuSpeakSlower);
  830.  
  831. /*    InstallMenu("\pTiming");*/
  832. /*    InstallItem("\pTime Some Stuff/K", MenuTimeTest);*/
  833.  
  834.     InstallMenu("\pIdle Tasks");
  835.     InstallItem("\pShow System Version/1", MenuSystemVersionTest);
  836.     InstallItem("\pMeasure Available RAM/2", MenuMeasureRAM);
  837.     InstallItem("\p(-", nil);
  838.     InstallItem("\pTrig Calculations/3", MenuToggleIdleTrigCalcs);
  839.     InstallItem("\pMemory Purge & Compact/4", MenuTogglePurgeCompact);
  840.     
  841.     BuildVoiceMenu();
  842.     OpenNewWindow();
  843.     MenuGetTextFile();
  844. }
  845.  
  846.  
  847.  
  848.